from django.shortcuts import render
from users.models import Address
from goods.models import SKU
from django_redis import get_redis_connection
from decimal import Decimal
from django import http
from django.utils import timezone
from django.db import transaction
import json

from meiduo_mall.utils.login_user import LoginUserView
from .models import OrderInfo, OrderGoods
from meiduo_mall.utils.response_code import RETCODE
import logging

logger = logging.getLogger()


class OrderSettlementView(LoginUserView):
    """结算页面"""

    def get(self, request):
        # 查出所有的非逻辑删除收获地址
        user = request.user
        addresses = Address.objects.filter(user=user, is_deleted=False)
        # 取出redis中的购物车数据
        redis_conn = get_redis_connection('carts')
        redis_dict = redis_conn.hgetall('carts_%s' % user.id)
        sku_ids = redis_conn.smembers('selected_%s' % user.id)
        # 准备一个空字典装已勾选的商品信息
        carts_dict = {}
        # 遍历购物车勾选集合把勾选的商品添加到空字典中
        for sku_id in sku_ids:
            carts_dict[int(sku_id)] = int(redis_dict[sku_id])
        # 通过sku_id 查出已勾选的商品模型skus
        skus = SKU.objects.filter(id__in=sku_ids)
        # 定义两个变量计算返回
        total_count = 0
        total_amount = 0
        # 遍历skus拿到每一个模型获取相应的属性
        for sku in skus:
            sku.count = carts_dict[sku.id]
            sku.amount = sku.count * sku.price
            total_count += sku.count
            total_amount += sku.amount
        # 运费
        freight = Decimal('10.00')
        # 包装模板进行渲染
        context = {
            'addresses': addresses,
            'skus': skus,
            'total_count': total_count,
            'total_amount': total_amount,
            'freight': freight,
            'payment_amount': total_amount + freight,
        }
        # 响应
        return render(request, 'place_order.html', context)


class OrderCommitView(LoginUserView):
    """提交订单"""

    def post(self, request):
        # 接收非表单数据
        json_dict = json.loads(request.body.decode())
        address_id = json_dict.get('address_id')
        pay_method = json_dict.get('pay_method')
        # 校验
        if all([address_id, pay_method]) is False:
            return http.HttpResponseForbidden('参数不全')
        user = request.user
        try:
            address = Address.objects.get(user=user, is_deleted=False, id=address_id)
        except Address.DoesNotExist:
            return http.HttpResponseForbidden('无效的address_id')
        if pay_method not in [OrderInfo.PAY_METHODS_ENUM['CASH'], OrderInfo.PAY_METHODS_ENUM['ALIPAY']]:
            return http.HttpResponseForbidden('参数错误')
        # 生成订单编号
        order_id = timezone.now().strftime('%Y%m%d%H%M%S') + '%09d' % user.id
        # 判断status状态
        status = (OrderInfo.ORDER_STATUS_ENUM['UNCOMMENT']
                  if (pay_method == OrderInfo.PAY_METHODS_ENUM['ALIPAY'])
                  else OrderInfo.ORDER_STATUS_ENUM['UNSEND'])
        # 运费
        freight = Decimal('10.00')
        # 1新增订单信息
        # 创建事物
        with transaction.atomic():
            # 创建事物保存点
            save_id1 = transaction.savepoint()
            try:
                order = OrderInfo.objects.create(
                    order_id=order_id,
                    user=user,
                    address=address,
                    total_count=0,  # 先设置为0，最后再修改
                    total_amount=Decimal('0.00'),  # 先设置为0,最后再修改
                    freight=freight,
                    pay_method=pay_method,
                    status=status,
                )
                # 从redis数据库中取出购物车数据
                redis_conn = get_redis_connection('carts')
                redis_dict = redis_conn.hgetall('carts_%s' % user.id)
                sku_ids = redis_conn.smembers('selected_%s' % user.id)
                carts_dict = {}
                for sku_id_bytes in sku_ids:
                    carts_dict[int(sku_id_bytes)] = int(redis_dict[sku_id_bytes])
                for sku_id in carts_dict:
                    while True:
                        # 通过sku_id查出模型
                        sku = SKU.objects.get(id=sku_id)
                        buy_count = carts_dict[sku_id]
                        # 2修改sku库存和销量
                        # 原有的库存量和销量
                        origin_stock = sku.stock
                        origin_sales = sku.sales
                        # 判断库存量是否充足
                        if buy_count > origin_stock:
                            # 库存不足回滚事物
                            transaction.savepoint_rollback(save_id1)
                            return http.JsonResponse({'code': RETCODE.STOCKERR, 'errmsg': '库存不足'})
                        # 修改库存量和销量并保存
                        new_stock = origin_stock - buy_count
                        new_sales = origin_sales + buy_count
                        # sku.stock = new_stock
                        # sku.sales = new_sales
                        # sku.save()
                        # 添加乐观锁
                        result = SKU.objects.filter(id=sku_id, stock=origin_stock).update(stock=new_stock,
                                                                                          sales=new_sales)
                        if result == 0:
                            continue
                        # 3修改spu销量
                        spu = sku.spu
                        spu.sales += buy_count
                        spu.save()
                        # 4新增订单中商品信息
                        order_goods = OrderGoods.objects.create(
                            order=order,
                            sku=sku,
                            count=buy_count,
                            price=sku.price
                        )
                        order.total_count += order_goods.count
                        order.total_amount += order_goods.price * order_goods.count
                        # 下单成功跳出循环
                        break
                    order.total_amount += order.freight
                    order.save()

            except Exception as e:
                logger.error(e)
                # 暴力回滚
                transaction.savepoint_rollback(save_id1)
                return http.JsonResponse({'code': RETCODE.STOCKERR, 'errmsg': '下单失败'})

            transaction.savepoint_commit(save_id1)
        # 清除购物车中已勾选的商品
        pl = redis_conn.pipeline()
        pl.hdel('carts_%s' % user.id, *carts_dict.keys())
        pl.delete('selected_%s' % user.id)
        pl.execute()
        # 响应
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'order_id': order_id})


class OrderSuccessView(LoginUserView):
    """订单成功"""

    def get(self, request):
        # 接收参数
        order_id = request.GET.get('order_id')
        payment_amount = request.GET.get('payment_amount')
        pay_method = request.GET.get('pay_method')
        # 校验
        try:
            order = OrderInfo.objects.get(user=request.user, order_id=order_id, total_amount=payment_amount,
                                          pay_method=pay_method)
        except OrderInfo.DoesNotExist:
            return http.HttpResponseForbidden('参数错误')
        # 包装响应内容
        context = {
            'order_id': order_id,
            'payment_amount': payment_amount,
            'pay_method': pay_method

        }
        # 响应
        return render(request, 'order_success.html', context)


class OrderCommentView(LoginUserView):
    """获取评论界面"""
    def get(self, request):
        # 获取数据order_id
        order_id = request.GET.get('order_id')
        try:
            order = OrderInfo.objects.get(order_id=order_id,user=request.user)
        except OrderInfo.DoesNotExist:
            return http.HttpResponseForbidden('order_id有误')
        skus = []
        order_goods_qs = order.skus.all()
        for order_goods in order_goods_qs:
            sku = SKU.objects.get(id=order_goods.sku_id)
            skus.append({
                'order_id':order_id,
                'name':sku.name,
                'sku_id':sku.id,
                'price':str(sku.price),
                'display_score': order_goods.score,
                'default_image_url':sku.default_image.url

            })
        return render(request,'goods_judge.html',{'uncomment_goods_list':skus})

    def post(self,request):
        """保存评论"""
        json_dict = json.loads(request.body.decode())
        order_id = json_dict.get('order_id')
        sku_id = json_dict.get('sku_id')
        comment = json_dict.get('comment')
        score = json_dict.get('score')
        is_anonymous = json_dict.get('is_anonymous')
        if not all([order_id,sku_id,comment]):
            return http.HttpResponseForbidden('缺少参数')
        try:
            order_goods = OrderGoods.objects.get(order_id=order_id,sku_id=sku_id)
        except OrderGoods.DoesNotExist:
            return http.HttpResponseForbidden('参数错误')
        if len(comment) < 5:
            return http.HttpResponseForbidden('请填写多余5个字的评价内容')
        if score > 5:
            return http.HttpResponseForbidden('参数错误')
        if isinstance(is_anonymous,bool) is False:
            return http.HttpResponseForbidden('参数错误')
        order_goods.order_id = order_id
        order_goods.sku_id = sku_id
        order_goods.comment = comment
        order_goods.score = score
        order_goods.is_anonymous = is_anonymous
        order_goods.is_commented = True
        order_goods.save()
        order = OrderInfo.objects.get(order_id=order_id)
        order.status = OrderInfo.ORDER_STATUS_ENUM['FINISHED']
        order.save()
        return http.JsonResponse({'code':RETCODE.OK,'errmsg':'OK'})
